package com.yzl.meeting.framework.beans.factory;

import com.yzl.meeting.framework.beans.PropertyValueResolver;
import com.yzl.meeting.framework.beans.exception.BeanCreateException;
import com.yzl.meeting.framework.beans.support.BeanDefinitionRegistry;
import com.yzl.meeting.framework.beans.support.DefaultSingletonBeanRegistry;
import com.yzl.meeting.framework.pojo.BeanDefinition;
import com.yzl.meeting.framework.pojo.PropertyValue;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Title: BeanFactoryImpl
 * @Author: 姚志立
 * @Description:
 * @Date: 2020/10/20 11:52
 * @Version: 1.0
 */
public class BeanFactoryImpl extends DefaultSingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry {
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();


    public BeanFactoryImpl() {
    }


    @Override
    public Object getBean(String beanId) {
        try {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanId);
            boolean singleton = beanDefinition.isSingleton();
            if (singleton) {
                Object bean = getSingleton(beanId);
                if (bean == null) {
                    bean = createBean(beanDefinition);//如果集合中没有该beanId,则创建一个新的bean
                    registerSinleton(beanId, bean);
                }
                return bean;
            }
            return createBean(beanDefinition);
        } catch (Exception e) {
            throw new BeanCreateException("创建" + beanId + "是失败", e);
        }
    }

    private Object createBean(BeanDefinition beanDefinition) throws IllegalAccessException, InstantiationException {
        Object bean = instantiate(beanDefinition);
        injectBean(bean, beanDefinition);
        return bean;

    }

    private void injectBean(Object bean, BeanDefinition beanDefinition) {
        List<PropertyValue> pvs = beanDefinition.getPropertyValueList();
        if (pvs == null || pvs.isEmpty()) {
            return;
        }
        PropertyValueResolver pvr = new PropertyValueResolver(this);
        try {
            for (PropertyValue pv : pvs) {
                String pname = pv.getPname();
                Object value = pv.getValue();
                BeanInfo beanInfo = Introspector.getBeanInfo(beanDefinition.getTypeClass());
                PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
                for (PropertyDescriptor pd : pds) {
                    if (pd.getName().equals(pname)) {
                        Method writeMethod = pd.getWriteMethod();
                        writeMethod.invoke(bean, pvr.resolveValue(value));
                    }
                }
            }
        } catch (Exception e) {
            throw new BeanCreateException("创建" + beanDefinition.getTypeName() + " 时出错", e);
        }
    }

    private Object instantiate(BeanDefinition beanDefinition) throws IllegalAccessException, InstantiationException {
        Object o = null;
        Class typeClass = beanDefinition.getTypeClass();
        o = typeClass.newInstance();
        return o;
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanId) {
        return beanDefinitionMap.get(beanId);
    }

    @Override
    public void registerBeanDefinition(String beanId, BeanDefinition beanDefinition) {
        beanDefinitionMap.put(beanId, beanDefinition);
    }
}
